package jsc.base;
import java.io.*;

/**
 * @author Marc Gaëtano
 */

/**
 * The class <tt>TextFileReader</tt> is a convenience class for reading text
 * files. The file to read is specified by a <tt>File</tt> object. An instance of
 * <tt>TextFileReader</tt> provides a buffered reader so as to provide for the
 * efficient reading of lines (strings).<p>
 *
 * A <tt>TextFileReader</tt> object can be seen as a text stream ending by
 * an end-of-file mark, and a cursor. After being created, a text stream
 * moves the cursor to the first line, or to the end-of-file mark if the
 * stream is empty.<p>
 *
 * A line is considered to be terminated by any one of a line feed ('\n'), a
 * carriage return ('\r'), or a carriage return followed immediately by a
 * linefeed.<p>
 *
 * All the public methods become invalid after the text file reader has been
 * closed.
 */
public class TextFileReader {

    private BufferedReader br; // the buffered char reader
    private String buffer;     // the current line
    private boolean eof;       // to know if the end of file has been reached
    private boolean closed;    // to know if the file has been closed

    /**
     * Create a buffered text file reader. After creation, move the cursor to the
     * first line of the file reader, or to the end of file if this file
     * reader is empty.
     * @param file the actual file to read strings from.
     * @throws IOException if the specified file is not found or if some other I/O
     * error occurs.
     */
    public TextFileReader(File f) throws IOException {
        br = new BufferedReader(new FileReader(f));
        closed = false;
        readNextLine();
    }

    /**
     * Tell whether the end of the text file reader is reached. The end of the
     * text file reader is reached when the cursor is pointing to the end-of-file mark.
     * @return <tt>true</tt> if the end of file is reached, <tt>false</tt>
     * otherwise.
     * @throws IOException if the text file reader is closed.
     */
    public boolean eof() throws IOException {
        if ( closed ) {
            throw new IOException("cannot eof: file is already closed");
        }
        return eof;
    }

    /**
     * Close the text file reader. The text file reader must be closed after the
     * end of use.
     * @throws IOException if the text file reader is already closed or if
     * some I/O error occurs.
     */
    public void close() throws IOException {
        if ( closed ) {
            throw new IOException("cannot close: file is closed");
        }
        br.close();
        closed = true;
    }

    /**
     * Return the current unread line of the text file reader.
     * The end of file must not have been reached, i.e. the cursor must not
     * be pointing to the end-of-file mark.
     * @return the current unread line, i.e. the line pointed by the
     * cursor.
     * @throws IOException if the end of file is reached or if the text
     * file reader is closed.
     */
    public String peek() throws IOException {
        if ( eof ) {
            throw new IOException("cannot peek: end of file reached");
        }
        if ( closed ) {
            throw new IOException("cannot peek: file is closed");
        }
        return buffer;
    }

    /**
     * Read and return the current unread line of the text file reader. After
     * reading move to the next line, or to the end of file if there is no more
     * line to read in this text file reader. A line is considered to be
     * terminated by any one of a line feed ('\n'), a carriage return ('\r'),
     * or a carriage return followed immediately by a linefeed.
     * @return the current unread line, i.e. the line pointed by the
     * cursor, <i>before</i> moving the cursor to the next line, or to the
     * end of file if there is no more line to read in this text file
     * reader. The line returned does not include any line-termination
     * characters.
     * @throws IOException if the end of file is reached, if the text
     * file reader is closed or if some other I/O error occurs.
    */
    public String read() throws IOException {
        if ( eof ) {
            throw new IOException("cannot read: end of file reached");
        }
        if ( closed ) {
            throw new IOException("cannot read: file is closed");
        }
        String s = buffer;
        readNextLine();
        return s;
    }

    // Move to the next line.
    private void readNextLine() throws IOException {
        String s = br.readLine();
        if ( s == null ) {
            eof = true;
        }
        else {
            buffer = s;
        }
    }
}
